#pragma once

#include "my_rbtree.h"
#include "my_queue.h"
#include "my_thread_base.h"

#define MY_POOL_PAGE_SIZE                   4096
#define MY_PAGE_MAX_ALLOC_SIZE              512
#define MY_POOL_ALLOC_ALIGNED_SIZE          8           // 8 Byte aligmen

typedef struct my_pool_s my_pool_t;

typedef void (*my_pool_cleanup_pt)(my_pool_t *pool, void *data);

typedef struct {
    my_queue_t                  queue;
    my_pool_cleanup_pt          cleanup;
    void                        *data;
} my_pool_cleanup_node_t;

typedef struct {
    my_rbtree_node_t            tree_node;
    my_queue_t                  queue;
    void                        *ptr;
} my_pool_block_node_t;

typedef struct {
    my_queue_t                  queue;
    char                        *start;
    char                        *end;
    char                        *pos;
} my_pool_page_t;

my_pool_page_t *my_pool_page_alloc();
void my_pool_page_free(my_pool_page_t *page);

struct my_pool_s {
    my_queue_t                  pages;
    my_pool_page_t              *cur_page;

    my_rbtree_t                 block_tree;
    my_rbtree_node_t            block_sentinel;

    my_queue_t                  cleanup_queue;
};

my_pool_t *my_pool_create();
void my_pool_destroy(my_pool_t *pool);

void *my_pool_mem_alloc(my_pool_t *pool, int64_t size);
void my_pool_mem_free(my_pool_t *pool, void *ptr);

static inline void *
my_pool_mem_calloc(my_pool_t *pool, int64_t size) {
    void *ptr = my_pool_mem_alloc(pool, size);
    bzero(ptr, (size_t)size);
    return ptr;
}

my_pool_cleanup_node_t *my_pool_add_cleanup(my_pool_t *pool,
    my_pool_cleanup_pt cleanup, void *data);
void my_pool_del_cleanup(my_pool_t *pool, my_pool_cleanup_node_t *cleanup_node);